package com.atguigu.dga.governance.assessor.calc;

import com.atguigu.dga.constant.DgaConstant;
import com.atguigu.dga.governance.assessor.Assessor;
import com.atguigu.dga.governance.bean.AssessParam;
import com.atguigu.dga.governance.bean.GovernanceAssessDetail;
import com.atguigu.dga.util.SqlUtil;
import org.apache.hadoop.hive.ql.lib.Dispatcher;
import org.apache.hadoop.hive.ql.lib.Node;
import org.apache.hadoop.hive.ql.parse.ASTNode;
import org.apache.hadoop.hive.ql.parse.HintParser;
import org.apache.hadoop.hive.ql.parse.HiveParser;
import org.apache.hadoop.hive.ql.parse.SemanticException;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.math.BigDecimal;
import java.net.URISyntaxException;
import java.text.ParseException;
import java.util.Stack;

/**
 * ClassName: SqlSelectStarAssessor
 * Package: com.atguigu.dga.governance.assessor.calc
 * Description:
 *
 * @Author:
 * @Create: 2024/3/20 14:32
 * @Version: 1.0
 */
@Component("SQL_SELECT_STAR")
public class SqlSelectStarAssessor extends Assessor {
    @Override
    public void checkProblem(AssessParam assessParam, GovernanceAssessDetail governanceAssessDetail) throws ParseException, URISyntaxException, IOException, InterruptedException, org.apache.hadoop.hive.ql.parse.ParseException, SemanticException {
        // 解析当前表的对应的sql 判断是否包含了select *
        // TODO 1 ods 表没有sql
        if(DgaConstant.DW_LEVEL_ODS.equals(assessParam.getTableMetaInfo().getTableMetaInfoExtra().getDwLevel())) {
            return;
        }

        // TODO 2 排除其他没有sql的
        if(assessParam.getTDsTaskDefinition()== null || assessParam.getTDsTaskDefinition().getTaskSQl() == null) {
            return;
        }

        // TODO 3 取sql
        String taskSql = assessParam.getTDsTaskDefinition().getTaskSQl();

        // TODO 4 先写SqlUtil工具方法 处理sql
        SelectStarDispatcher selectStarDispatcher = new SelectStarDispatcher();
        SqlUtil.parseSql(taskSql, selectStarDispatcher);

        // TODO 5 判断
        if(selectStarDispatcher.isContainsSelectStar) {
            governanceAssessDetail.setAssessScore(BigDecimal.ZERO);
            governanceAssessDetail.setAssessProblem("sql包含select *");
        }
    }
    // TODO 4 自定义传入parseSql() 对每个节点做什么处理的dispatcher
    public static class SelectStarDispatcher implements Dispatcher {
        private Boolean isContainsSelectStar = false;

        /**
         *
         * @param node 当前被遍历的节点
         * @param stack
         * @param objects
         * @return
         * @throws SemanticException
         */
        @Override
        public Object dispatch(Node node, Stack<Node> stack, Object... objects) throws SemanticException {
            ASTNode astNode = (ASTNode) node;
            if(astNode.getType() == HiveParser.TOK_ALLCOLREF) { // TOK_ALLCOLREF 代表 select *， 可以在工具类里测试出
                isContainsSelectStar = true;
            }
            return null;
        }
    }
}
